﻿using System;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace BitworkStudios.Web.Mvc.Framework.Navigation
{
    public class RouteInfo
    {
        public RouteData RouteData { get; private set; }

        public static HttpContextBase CurrentHttpContext
        {
            get
            {
                var context = new HttpContextWrapper(HttpContext.Current);
                return context;
            }
        }

        public static RequestContext CurrentHttpRequestContext
        {
            get
            {
                return CurrentHttpContext.Request.RequestContext;
            }
        }

        public static string CurrentApplicationPath
        {
            get
            {
                return CurrentHttpContext.Request.ApplicationPath;
            }
        }

        public static UrlHelper Url
        {
            get
            {
                return new UrlHelper(CurrentHttpRequestContext);
            }
        }

        public RouteInfo(RouteData data)
        {
            RouteData = data;
        }

        public RouteInfo(Uri uri, string applicationPath)
        {
            RouteData = RouteTable.Routes.GetRouteData(new InternalHttpContext(uri, applicationPath));
        }

        private class InternalHttpContext : HttpContextBase
        {
            private readonly HttpRequestBase _request;

            public InternalHttpContext(Uri uri, string applicationPath)
            {
                _request = new InternalRequestContext(uri, applicationPath);
            }

            public override HttpRequestBase Request
            {
                get { return _request; }
            }
        }

        private class InternalRequestContext : HttpRequestBase
        {
            private readonly string _appRelativePath;
            private readonly string _pathInfo;

            public InternalRequestContext(Uri uri, string applicationPath)
            {
                _pathInfo = uri.Query;

                if (String.IsNullOrEmpty(applicationPath) ||
                    !uri.AbsolutePath.StartsWith(applicationPath, StringComparison.OrdinalIgnoreCase))
                    _appRelativePath = uri.AbsolutePath.Substring(applicationPath.Length);
                else
                    _appRelativePath = uri.AbsolutePath;
            }

            public override string AppRelativeCurrentExecutionFilePath
            {
                get { return String.Concat("~", _appRelativePath); }
            }

            public override string PathInfo
            {
                get { return _pathInfo; }
            }
        }

        /// <summary>
        /// Converts the provided app-relative path into an absolute Url containing the full host name
        /// </summary>
        /// <param name="relativeUrl">App-Relative path</param>
        /// <returns>Provided relativeUrl parameter as fully qualified Url</returns>
        /// <example>~/path/to/foo to http://www.web.com/path/to/foo</example>
        public static string ToAbsoluteUrl(string relativeUrl)
        {
            if (string.IsNullOrEmpty(relativeUrl))
                return relativeUrl;

            if (HttpContext.Current == null)
                return relativeUrl;

            if (relativeUrl.StartsWith("/"))
                relativeUrl = relativeUrl.Insert(0, "~");
            if (!relativeUrl.StartsWith("~/"))
                relativeUrl = relativeUrl.Insert(0, "~/");

            var url = HttpContext.Current.Request.Url;
            var port = url.Port != 80 ? (":" + url.Port) : String.Empty;

            return String.Format("{0}://{1}{2}{3}",
                   url.Scheme, url.Host, port, VirtualPathUtility.ToAbsolute(relativeUrl));
        }

    }
}
